package cards;
import java.util.Stack;
/** the solution is a sequence of cards placed on the board according to the card positions
    example without border
*/
public class Solution extends Stack<Candidate>
{
    // The board is an 2D array.
	// 0123
	// 0..-.
	// 1---.
	// 2.---
	// 3..-.
	private Candidate[][] board = new Candidate[4][4];
	
	// card positions on the board
	// the first card position on the board are
	// {0,2}, {1,0}. {1,1}
	private int[] row    = { 0, 1, 1, 1, 2, 2, 2, 3 };
	private int[] column = { 2, 0, 1, 2, 1, 2, 3, 2 };
	//  indices of adjacent cards in the solution.
	//                 0   1  2   3   4    5     6    7   
	int [] [] check = {{},{},{1},{0},{2},{3,4},{5,6},{7}}; 
	
	
	public Solution(){
	}

	
	 // Checks whether a candidate with card CardChar is in 
	 // an adjacent position of the board position (row, column)
	 // @param row, column, candidate
	 // @return Boolean indicating if cardChar is found.
	 // can be used in the methods fits and isCorrect
	private boolean bordersCard(int row, int column, char cardChar){
		if(row == 2){
			if(board[this.row[row-1]][this.column[column-1]].getCardChar() == cardChar){
				return false;
			}
		} else if(row == 3){
			if(board[this.row[row-1]][this.column[column-1]].getCardChar() == cardChar || 
					board[this.row[row-3]][this.column[column-3]].getCardChar() == cardChar)
				return false;
		} else if(row == 4){
			if(board[this.row[row-2]][this.column[column-2]].getCardChar() == cardChar){
				return false;
			}
		} else if(row == 5){
			if(board[this.row[row-1]][this.column[column-1]].getCardChar() == cardChar ||
					board[this.row[row-2]][this.column[column-2]].getCardChar() == cardChar){
				return false;
			}
		} else if(row == 6){
			if(board[this.row[row-1]][this.column[column-1]].getCardChar() == cardChar){
				return false;
			}
		} else if(row == 7){
			if(board[this.row[row-2]][this.column[column-2]].getCardChar() == cardChar){
				return false;
			}
		}
				
		 return true;
		
    }
	
	
	/**
	 * Checks whether candidate card of same kind.
	 * Checks whether by placing candidate the solution sofar still complies with the rules
	 * @param candidate
	 * @return boolean indicating whether this candidate can be put in the
	 * next free position.
	 */
	public boolean fits(Candidate candidate){ 
		int i = this.size();
		char mustBeAdjecent = mustBeAdjacentTo(candidate.getCardChar());
		char cardChar = candidate.getCardChar();
		if(bordersCard(i, i, cardChar)){
			if(mustBeAdjecent == '?'){
				return true;
			}else{
				if(i == 0){
					return true;
				} else if(i == 1){
					return true;
				} else if(i == 2){
					if(board[this.row[i-1]][this.column[i-1]].getCardChar() == mustBeAdjecent){
						return true;
					}
				} else if(i == 3){
					if(board[this.row[1]][this.column[1]].getCardChar() == mustBeAdjecent){
						return true;
					}
				} else if(i == 4){
					if(board[this.row[0]][this.column[0]].getCardChar() == mustBeAdjecent ||
							board[this.row[2]][this.column[2]].getCardChar() == mustBeAdjecent){
						return true;
					}
				} else if(i == 5){
					if(board[this.row[2]][this.column[2]].getCardChar() == mustBeAdjecent){
						return true;
					}
				} else if(i == 6){
					if(board[this.row[3]][this.column[3]].getCardChar() == mustBeAdjecent ||
							board[this.row[4]][this.column[4]].getCardChar() == mustBeAdjecent){
						return true;
					}
				} else if(i == 7){
					if(board[this.row[5]][this.column[5]].getCardChar() == mustBeAdjecent){
						return true;
					}
				} else if(i == 8){
					if(board[this.row[5]][this.column[5]].getCardChar() == mustBeAdjecent){
						return true;
					}
				}
			}
		}
	    return false;
    }

	public void record(Candidate candidate)
	{
		int i=this.size(); // i= index in this stack of next for the next candidate
		board [row[i]] [column[i]] = candidate; //x=row, y=column
		this.push(candidate);
		System.out.println("placed "+ candidate.getCardChar()+ " on " + i);
		
	}

	public boolean complete()
	{
		return this.size()==8;
	}

	public void show()
	{
		System.out.println(this); 
	}

	public Candidate eraseRecording()
	{
		int i=this.size()-1;           // i= index of the candidate that is removed from this Stack;
		board[row[i]][column[i]]=null; // remove candidate from board
		return this.pop();
    }
	
	// can be used in method isCorrect
    private char mustBeAdjacentTo(char card)
    {  
      if (card=='A') return 'K'; 
      if (card=='K') return 'Q'; 
      if (card=='Q') return 'J';
      return '?'; //error
    }
	
	/**
	 * Checks whether the rules below are fulfilled
	 * For the positions that can be checked for solution sofar.
	 * Rules:
	 * Elke aas (ace) grenst (horizontaal of verticaal) aan een heer (king).
	 * Elke heer grenst aan een vrouw (queen).
	 * Elke vrouw grenst aan een boer (jack).
	 * @return true if all checks are correct.
	 */
	// uses methods borderCard and mustBeAdjacent to
	private boolean isCorrect() {
       //TODO
		return false;
     }     
            
	
	/**
	 * @return a representation of the solution on the board
	 */
     public String toString(){
    	System.out.println("XX"+board[this.row[0]][this.column[0]].getCardChar()+"X");
    	System.out.println("" + (board[this.row[1]][this.column[1]].getCardChar()) + (board[this.row[2]][this.column[2]].getCardChar()) +board[this.row[3]][this.column[3]].getCardChar()+"X");
    	System.out.println("X"+board[this.row[4]][this.column[4]].getCardChar() + board[this.row[5]][this.column[5]].getCardChar() + board[this.row[6]][this.column[6]].getCardChar());
    	System.out.println("XX"+board[this.row[7]][this.column[7]].getCardChar()+"X");
    	
	    return "";
	}    

}
